package com.trz.cqrs.core.priority;


import com.trz.cqrs.core.entity.EventEntity;
import com.trz.cqrs.es.event.priority.Priority;
import com.trz.cqrs.es.event.priority.Strategy;
import lombok.val;
import lombok.var;
import org.springframework.stereotype.Component;

import static java.lang.Math.min;
import static java.lang.Math.sqrt;

@Component
public class DecelerateDescentStrategy implements PriorityStrategy {

    @Override
    public Strategy getStrategy() {
        return Strategy.DECELERATE_DESCENT;
    }

    @Override
    public void adjust(EventEntity entity) {
        /*
         * f(c, p) = min(*, 8)
         * case c = 0
         *      * = p or 4 * (p % 9)
         * case p in [0, 9)
         *      n = sqrt((c - offset) * 1.0d / scale)
         *      * = p + (n == (int) n ? 1 : 0)
         * case p in [9, 12)
         *      n = sqrt((c - offset) * 1.0d / scale)
         *      * = 4 * (p % 9) + (n == (int) n ? 1 : 0)
         */
        val c = entity.getCount();
        val p = entity.getPriority().ordinal();

        val offset = 330;
        val scale = 30;

        var delta = 0;
        if (c > offset && c % scale == 0) {
            val n = sqrt((c - offset) * 1.0d / scale);
            delta = (n == (int) n) ? 1 : 0;
        }
        entity.setPriority(Priority.values()[min((p / 9 * 3 + 1) * (p % 9) + delta, 8)]);
    }

}
